package com.google.gwt.mobile.phonegap.api;

import java.util.Date;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.mobile.phonegap.DeviceType;
import com.google.gwt.mobile.phonegap.PhoneGap;

/**
 * The Class Geolocation.
 */
public class Geolocation {

  /**
   * Gets the current position.
   * 
   * @param callback the callback
   * @return the current position
   */
  public static native void getCurrentPosition(Callback callback) /*-{
		$wnd.navigator.geolocation
				.getCurrentPosition(
						function(position) {
							$wnd.console.log("gwt getcurrentposition");
							callback.@com.google.gwt.mobile.phonegap.api.Geolocation.Callback::onSuccess(Lcom/google/gwt/mobile/phonegap/api/Geolocation$Position;)(position);
						},
						function(error) {
							callback.@com.google.gwt.mobile.phonegap.api.Geolocation.Callback::onError(Lcom/google/gwt/mobile/phonegap/api/Geolocation$PositionError;)(error);
						});
  }-*/;

  /**
   * Watch position.
   * 
   * @param callback the callback
   * @return the string
   */
  public static String watchPosition(final Callback callback) {
    return watchPosition(callback, (JavaScriptObject) null);
  }

  /**
   * Watch position.
   * 
   * @param callback the callback
   * @param options the options
   * @return the string
   */
  public static String watchPosition(final Callback callback, final Options options) {
    return watchPosition(callback, options.getOptions());
  }

  private static native String watchPosition(Callback callback, JavaScriptObject options) /*-{
		var id = $wnd.navigator.geolocation
				.watchPosition(
						function(position) {
							callback.@com.google.gwt.mobile.phonegap.api.Geolocation.Callback::onSuccess(Lcom/google/gwt/mobile/phonegap/api/Geolocation$Position;)(position);
						},
						function(error) {
							callback.@com.google.gwt.mobile.phonegap.api.Geolocation.Callback::onError(Lcom/google/gwt/mobile/phonegap/api/Geolocation$PositionError;)(error);
						}, options);
		return id;
  }-*/;

  /**
   * Clear watch.
   * 
   * @param watchId the watch id
   */
  public static native void clearWatch(String watchId) /*-{
		$wnd.navigator.geolocation.clearWatch(watchId);
  }-*/;

  /**
   * The Interface Callback.
   */
  public interface Callback {
    void onSuccess(Position position);

    void onError(PositionError error);
  }

  /**
   * The Class Position.
   */
  public static class Position extends JavaScriptObject {
    protected Position() {
    };

    /**
     * Gets the coords.
     * 
     * @return the coords
     */
    public native final Coordinates getCoords() /*-{
			return this.coords;
    }-*/;

    /**
     * Gets the timestamp.
     * 
     * @return the timestamp
     */
    @SuppressWarnings("deprecation")
    public final Date getTimestamp() {
      if (PhoneGap.RUNTIME.getDeviceType() == DeviceType.IOS) {
        return new Date((long) getTimestampDoubleNative());
      } else {
        return new Date(getTimestampStringNative());
      }
    }

    private native final String getTimestampStringNative() /*-{
			return this.timestamp;
    }-*/;

    private native final double getTimestampDoubleNative() /*-{
			return this.timestamp * 1000;
    }-*/;
  }

  /**
   * The Class Coordinates.
   */
  public static class Coordinates extends JavaScriptObject {
    protected Coordinates() {
    };

    /**
     * Gets the latitude.
     * 
     * @return the latitude
     */
    public native final double getLatitude() /*-{
			return this.latitude;
    }-*/;

    /**
     * Gets the longitude.
     * 
     * @return the longitude
     */
    public native final double getLongitude() /*-{
			return this.longitude;
    }-*/;

    /**
     * Gets the altitude.
     * 
     * @return the altitude
     */
    public native final double getAltitude() /*-{
			return this.altitude;
    }-*/;

    /**
     * Gets the accuracy.
     * 
     * @return the accuracy
     */
    public native final float getAccuracy() /*-{
			return this.accuracy;
    }-*/;

    /**
     * Gets the altitude accuracy.
     * 
     * @return the altitude accuracy
     */
    public native final float getAltitudeAccuracy() /*-{
			return this.altitudeAccuracy;
    }-*/;

    /**
     * Gets the heading.
     * 
     * @return the heading
     */
    public native final float getHeading() /*-{
			return this.heading;
    }-*/;

    /**
     * Gets the speed.
     * 
     * @return the speed
     */
    public native final double getSpeed() /*-{
			return this.speed;
    }-*/;
  }

  /**
   * The Class PositionError.
   */
  public static class PositionError extends JavaScriptObject {
    protected PositionError() {
    };

    /**
     * Gets the code.
     * 
     * @return the code
     */
    public native final String getCode() /*-{
			return this.code;
    }-*/;

    /**
     * Gets the message.
     * 
     * @return the message
     */
    public native final String getMessage() /*-{
			return this.message;
    }-*/;
  }

  /**
   * The Class Options.
   */
  public static class Options {
    Options self = this;
    JavaScriptObject options = JavaScriptObject.createObject();

    /**
     * Frequency.
     * 
     * @param f the f
     * @return the options
     */
    public native Options frequency(int f) /*-{
			this.@com.google.gwt.mobile.phonegap.api.Geolocation.Options::options.frequency = f;
			return this.@com.google.gwt.mobile.phonegap.api.Geolocation.Options::self;
    }-*/;

    /**
     * Enable high accuracy.
     * 
     * @param b the b
     * @return the options
     */
    public native Options enableHighAccuracy(boolean b) /*-{
			this.@com.google.gwt.mobile.phonegap.api.Geolocation.Options::options.enableHighAccuracy = b;
			return this.@com.google.gwt.mobile.phonegap.api.Geolocation.Options::self;
    }-*/;

    /**
     * Timeout.
     * 
     * @param t the t
     * @return the options
     */
    public native Options timeout(int t) /*-{
			this.@com.google.gwt.mobile.phonegap.api.Geolocation.Options::options.timeout = t;
			return this.@com.google.gwt.mobile.phonegap.api.Geolocation.Options::self;
    }-*/;

    /**
     * Maximum age.
     * 
     * @param a the a
     * @return the options
     */
    public native Options maximumAge(int a) /*-{
			this.@com.google.gwt.mobile.phonegap.api.Geolocation.Options::options.maximumAge = a;
			return this.@com.google.gwt.mobile.phonegap.api.Geolocation.Options::self;
    }-*/;

    private JavaScriptObject getOptions() {
      return options;
    }

  }

}
